package com.ZeroCarbon.service.impl;

import com.ZeroCarbon.common_service.CommonService;
import com.ZeroCarbon.domain.dto.CommentDTO;
import com.ZeroCarbon.domain.dto.UsernameAndAvatarDTO;
import com.ZeroCarbon.domain.po.Comment;
import com.ZeroCarbon.exception.BusinessLogicException;
import com.ZeroCarbon.mapper.CommentMapper;
import com.ZeroCarbon.service.ICommentService;
import com.ZeroCarbon.service.IUserCommentService;
import com.ZeroCarbon.utils.BusinessMethodUtils;
import com.ZeroCarbon.utils.UserHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

import static com.ZeroCarbon.exception.BusinessLogicException.ERROR_EXCEPTION;
import static com.ZeroCarbon.prefix.MySqlKey.COMMENT_PREFIX;
import static com.ZeroCarbon.prefix.MySqlKey.generateId;
import static com.ZeroCarbon.prefix.RedisKey.THUMB_COMMENT;

@Slf4j
@Service
@RequiredArgsConstructor
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements ICommentService {

    private final IUserCommentService userCommentService;

    private final StringRedisTemplate redis;

    private CommonService<Comment> serviceUtils;

    @Autowired
    public void initServiceUtils(CommentMapper commentMapper) {
        serviceUtils = new CommonService<>(commentMapper);
    }

    /**
     * 发布评论
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void postComment(Comment comment) throws BusinessLogicException {
        //生成id
        String id = generateId(COMMENT_PREFIX);
        //设置评论信息
        comment.setLiked(0)
                .setDay(LocalDateTime.now())
                .setId(id);
        try {
            //保存评论
            if (!save(comment)) {
                throw new BusinessLogicException();
            }
        } catch (Exception e) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
        //保存信息失败
        if (!userCommentService.postComment(id)) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
    }

    /**
     * 获取所有评论
     *
     * @param id 商品id
     */
    @Override
    public List<CommentDTO> getComments(String id) throws BusinessLogicException {
        //评论构造器
        LambdaQueryWrapper<Comment> commentWrapper = new LambdaQueryWrapper<Comment>()
                .eq(Comment::getRecordId, id);
        //记录评论集合
        List<Comment> comments;
        try {
            //获取评论构造器
            comments = list(commentWrapper);
        } catch (Exception e) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
        //处理信息
        return comments.stream()
                .map(comment -> {
                    //转化对象
                    CommentDTO commentDTO = comment.toCommentDTO();
                    //获取用户名和头像
                    UsernameAndAvatarDTO usernameAndAvatar = userCommentService.getUsernameAndAvatar(comment.getId());
                    //设置额外信息
                    return commentDTO.setUsername(usernameAndAvatar.getUsername())
                            .setAvatar(usernameAndAvatar.getAvatar())
                            .setUserId(usernameAndAvatar.getUserId());
                }).collect(Collectors.toList());
    }

    /**
     * 点赞评论
     */
    @Override
    public int thumbsUpComment(String id) throws BusinessLogicException {
        //获取用户id
        String userId = UserHolder.getUser();
        //点赞key
        String key = THUMB_COMMENT + id;
        //点赞构造器
        LambdaQueryWrapper<Comment> likedWrapper = new LambdaQueryWrapper<Comment>()
                .select(Comment::getLiked)
                .eq(Comment::getId, id);
        //已点赞再次点击则取消赞
        int step = BusinessMethodUtils.isExist(key, userId) ? -1 : 1;
        try {
            //更新点赞
            Boolean isSuccess = serviceUtils.updateSqlIncrementOrCheck("liked", step, id);
            //修改redis中的记录
            if (step > 0 && isSuccess) {
                redis.opsForSet().add(key, userId);
            } else {
                redis.opsForSet().remove(key, userId);
            }
            return getOne(likedWrapper).getLiked();
        } catch (Exception e) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
    }

    /**
     * 判断用户是否点赞该评论
     *
     * @param id 评论id
     */
    @Override
    public Boolean isUserLikeShopComment(String id) throws BusinessLogicException {
        //获取用户id
        String userId = UserHolder.getUser();
        //点赞key
        String key = THUMB_COMMENT + id;
        try {
            //判断是否存在
            return BusinessMethodUtils.isExist(key, userId);
        } catch (Exception e) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
    }

    /**
     * 删除用户对于商品的评论
     *
     * @param id 评论id
     */
    @Override
    public void deleteComment(String id) throws BusinessLogicException {
        //删除redis相关评论键
        String key = THUMB_COMMENT + id;
        try {
            //删除键
            redis.delete(key);
            //删除失败抛出异常
            if (!removeById(id)) {
                throw new BusinessLogicException();
            }
        } catch (BusinessLogicException e) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
    }
}
